package com.ssm.basis.service.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.MessageSourceAccessor;

import java.util.Locale;

import static java.util.Objects.isNull;

/**
 * @see MessageSourceAccessor
 */
public abstract class MessageHelper {
    static final Object[] EMPTY_ARGS = new Object[]{};
    static MessageSource messageSource;
    // volatile 禁止指令重排，所有的写（write）操作都将发生在读（read）操作之前，保证分配内存、初始化、设置引用的顺序
    static volatile MessageSourceAccessor messageSourceAccessor;

    /**
     * @param code：对应文本配置的key.
     * @return 对应地区的语言消息字符串
     */
    public static String getMessage(String code) {
        return getMessage(code, EMPTY_ARGS);
    }

    public static String getMessage(String code, String defaultMessage) {
        return getMessage(code, null, defaultMessage);
    }

    public static String getMessage(String code, String defaultMessage, Locale locale) {
        return getMessage(code, null, defaultMessage, locale);
    }

    public static String getMessage(String code, Locale locale) {
        return getMessage(code, null, "", locale);
    }

    public static String getMessage(String code, Object[] args) {
        return getMessage(code, args, "");
    }

    public static String getMessage(String code, Object[] args, Locale locale) {
        return getMessage(code, args, "", locale);
    }

    public static String getMessage(String code, Object[] args, String defaultMessage) {
        Locale locale = LocaleContextHolder.getLocale();
        return getMessage(code, args, defaultMessage, locale);
    }

    public static String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
        return messageSource.getMessage(code, args, defaultMessage, locale);
    }

    // 提供一个静态的公有方法，加入双重检查代码，解决线程安全问题, 同时解决懒加载问题，同时保证了效率
    public static MessageSourceAccessor getMessageSourceAccessor() { // 双端检锁 Double Check Lock
        if (isNull(messageSourceAccessor)) { // 如果先设置引用，这里就会出现问题，会返回未初始化好的对象
            synchronized (MessageHelper.class) {
                if (isNull(messageSourceAccessor)) {
                    // 分配内存、初始化、设置引用
                    messageSourceAccessor = new MessageSourceAccessor(messageSource, LocaleContextHolder.getLocale());
                }
            }
        }
        return messageSourceAccessor;
    }

    @Autowired
    void setMessageSource(MessageSource messageSource) {
        MessageHelper.messageSource = messageSource;
    }
}